package com.uchiha.nova.mainService.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.uchiha.nova.mainService.mapper.BtnInfoMapper;
import com.uchiha.nova.mainService.mapper.NavMenuMapper;
import com.uchiha.nova.mainService.mapper.RoleMapper;
import com.uchiha.nova.mainService.mapper.RoleNavMenuMapper;
import com.uchiha.nova.mainService.service.INavMenuService;
import com.uchiha.nova.mainService.service.ITenantNavMenuService;
import com.uchiha.nova.core.tool.constant.NovaDefaultConstant;
import com.uchiha.nova.core.model.dto.TenantDTO;
import com.uchiha.nova.core.model.entity.NavMenuEntity;
import com.uchiha.nova.core.model.entity.RoleEntity;
import com.uchiha.nova.core.model.entity.RoleNavMenu;
import com.uchiha.nova.core.model.entity.TenantNavMenu;
import com.uchiha.nova.core.model.vo.NavMenuVO;
import com.uchiha.nova.core.model.vo.RoleSelectVO;
import com.uchiha.nova.core.model.vo.TenantNavMenuSelectVO;
import com.uchiha.nova.core.model.vo.TreeVO;
import com.uchiha.nova.core.tool.support.BaseServiceImpl;
import com.uchiha.nova.core.tool.support.DictBizVO;
import com.uchiha.nova.core.tool.util.CascaderUtil;
import com.uchiha.nova.core.tool.util.Func;
import com.uchiha.nova.mainService.wrapper.NavMenuWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 侧边栏 服务实现类
 *
 * @author Chill
 */
@Service
@Slf4j
public class NavMenuServiceImpl extends BaseServiceImpl<NavMenuMapper, NavMenuEntity> implements INavMenuService {

    @Resource
    RoleNavMenuMapper roleNavMenuMapper;
    @Resource
    RoleMapper roleMapper;
    @Resource
    ITenantNavMenuService tenantNavMenuService;
    @Resource
    BtnInfoMapper btnInfoMapper;


    @Override
    public boolean deletePhysics(List<Long> ids) {
        ids.forEach(item -> {
            Long a = this.baseMapper.selectCount(new QueryWrapper<NavMenuEntity>().eq("status",1).eq("id",item));
            if(a.compareTo(0L)==0){
                this.baseMapper.deletePhysics(item);
            }

        });
        return true;
    }

    @Override
    public List<NavMenuVO> getByRoles(List<RoleEntity> roles) {
        List<RoleNavMenu> allRoleNavMenu = new ArrayList<>();
        roles.forEach(item -> {
            List<RoleNavMenu> roleNavMenus = roleNavMenuMapper.selectList(new QueryWrapper<RoleNavMenu>().eq("role_id", item.getId()));
            allRoleNavMenu.addAll(roleNavMenus);
        });
        List<NavMenuVO> allNavMenu = new ArrayList<>();
        List<RoleNavMenu> finalRoleNavMenu = allRoleNavMenu.stream().distinct().collect(Collectors.toList());
        finalRoleNavMenu.forEach(item -> {
            NavMenuEntity navMenu = this.getById(item.getNavMenuId());
            NavMenuVO navMenuVO = BeanUtil.copyProperties(navMenu, NavMenuVO.class);
            navMenuVO.setSort(ObjectUtil.isEmpty(navMenu.getSort()) ? 0 : navMenu.getSort());
            allNavMenu.add(navMenuVO);
        });

        List<NavMenuVO> listLevelTop = allNavMenu.stream().filter(navMenu ->
                navMenu.getParentId().equals(0L)
        ).sorted(Comparator.comparing(NavMenuVO::getSort)).map(item -> {
            item.setFullPath(item.getPath());
            Long a = allNavMenu.stream().filter(item2 -> item2.getParentId().equals(item.getId())).count();
            if (a.compareTo(0L) == 1) {
                item.setChildren(getChildrens(item, allNavMenu));
            } else {
                item.setChildren(null);
            }

            return item;
        }).collect(Collectors.toList());
        return listLevelTop;
    }

    private List<NavMenuVO> getChildrens(NavMenuVO root, List<NavMenuVO> all) {
        List<NavMenuVO> children = all.stream().filter(navMenuVO ->
                navMenuVO.getParentId().equals(root.getId())
        ).sorted(Comparator.comparing(NavMenuVO::getSort)).map(item -> {
            //1、找到子菜单
            item.setFullPath(root.getFullPath()+item.getPath());
            Long a = all.stream().filter(item2 -> item2.getParentId().equals(item.getId())).count();
            if (a.compareTo(0L) == 1) {
                item.setChildren(getChildrens(item, all));
            } else {
                item.setChildren(null);
            }
            return item;
        }).collect(Collectors.toList());

        return children;
    }

    @Override
    public List<NavMenuVO> getTree(Long parentId) {
        List<NavMenuEntity> navMenus = this.list(new QueryWrapper<NavMenuEntity>().eq("parent_id", parentId));
        List<NavMenuVO> list = NavMenuWrapper.build().listNodeVO(navMenus);
        return list;
    }

    @Override
    public List<TreeVO> getTreeAll() {
        List<NavMenuEntity> allRoleNavMenu = this.list();
        List<TreeVO> treeVOS = allRoleNavMenu.stream().map(navMenu -> {
            TreeVO treeVO = new TreeVO();
            treeVO.setLabel(navMenu.getLabel());
            treeVO.setId(navMenu.getId());
            treeVO.setParentId(navMenu.getParentId());
            return treeVO;
        }).collect(Collectors.toList());
        List<TreeVO> listLevelTop = treeVOS.stream().filter(navMenu ->
                navMenu.getParentId().equals(0L)
        ).map(item -> {
            Long a = treeVOS.stream().filter(item2 -> item2.getParentId().equals(item.getId())).count();
            if (a.compareTo(0L) == 1) {
                item.setChildren(getChildrenTree(item, treeVOS));
            } else {
                item.setChildren(null);
            }
            return item;
        }).collect(Collectors.toList());
        return listLevelTop;
    }

    private List<TreeVO> getChildrenTree(TreeVO root, List<TreeVO> all) {
        List<TreeVO> children = all.stream().filter(treeVO ->
                treeVO.getParentId().equals(root.getId())
        ).map(item -> {
            //1、找到子菜单
            Long a = all.stream().filter(item2 -> item2.getParentId().equals(item.getId())).count();
            if (a.compareTo(0L) == 1) {
                item.setChildren(getChildrenTree(item, all));
            } else {
                item.setChildren(null);
            }
            return item;
        }).collect(Collectors.toList());

        return children;
    }

    @Override
    public List<String> getRoleHasSelect(Long roleId) {
        List<String> list = new ArrayList<>();
        List<RoleNavMenu> roleNavMenus = roleNavMenuMapper.selectList(new QueryWrapper<RoleNavMenu>().eq("role_id", roleId));
        roleNavMenus.forEach(item -> {
            list.add(String.valueOf(item.getNavMenuId()));
        });
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveRoleSelectVO(RoleSelectVO roleSelectVO) {
        Long roleId = roleSelectVO.getRoleId();
        roleNavMenuMapper.delete(new QueryWrapper<RoleNavMenu>().eq("role_id", roleId));
        roleSelectVO.getIds().forEach(item -> {
            RoleNavMenu roleNavMenu = new RoleNavMenu();
            roleNavMenu.setNavMenuId(item);
            roleNavMenu.setRoleId(roleId);
            roleNavMenuMapper.insert(roleNavMenu);
        });
        return true;
    }

    @Override
    public List<TreeVO> getTreeTenantAll(String roleName) {
        RoleEntity roleEntity = roleMapper.selectOne(new QueryWrapper<RoleEntity>().eq("role_name", roleName));
        List<NavMenuEntity> allRoleNavMenu = this.listByRole(roleEntity.getId());
        List<TreeVO> treeVOS = allRoleNavMenu.stream().map(navMenu -> {
            TreeVO treeVO = new TreeVO();
            treeVO.setLabel(navMenu.getLabel());
            treeVO.setId(navMenu.getId());
            treeVO.setParentId(navMenu.getParentId());
            return treeVO;
        }).collect(Collectors.toList());
        List<TreeVO> listLevelTop = treeVOS.stream().filter(navMenu ->
                navMenu.getParentId().equals(0L)
        ).map(item -> {
            Long a = treeVOS.stream().filter(item2 -> item2.getParentId().equals(item.getId())).count();
            if (a.compareTo(0L) == 1) {
                item.setChildren(getChildrenTree(item, treeVOS));
            } else {
                item.setChildren(null);
            }
            return item;
        }).collect(Collectors.toList());
        return listLevelTop;
    }

    private List<NavMenuEntity> listByRole(Long RoleId) {
        return baseMapper.listByRole(RoleId);
    }

    @Override
    public List<String> tenantHasSelect(String tenantId) {
        List<String> list = new ArrayList<>();
        List<TenantNavMenu> roleNavMenus = tenantNavMenuService.list(new QueryWrapper<TenantNavMenu>().eq("tenant_id", tenantId));
        roleNavMenus.forEach(item -> {
            list.add(String.valueOf(item.getNavMenuId()));
        });
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveTenantSelectVO(TenantNavMenuSelectVO tenantNavMenuSelectVO) {
        String tenantId = tenantNavMenuSelectVO.getTenantId();
        tenantNavMenuService.remove(new QueryWrapper<TenantNavMenu>().eq("tenant_id", tenantId));
        List<TenantNavMenu> tenantNavMenus = tenantNavMenuSelectVO.getNavMenuIds().stream().map(item -> {
            TenantNavMenu tenantNavMenu = new TenantNavMenu();
            tenantNavMenu.setNavMenuId(item);
            tenantNavMenu.setTenantId(tenantId);
            return tenantNavMenu;
        }).collect(Collectors.toList());
        if (tenantNavMenus.size() > 0) {
            tenantNavMenuService.saveBatch(tenantNavMenus);
        }
        return true;
    }

    @Override
    public List<TreeVO> tenantCanSelect(String tenantId) {
        List<TenantNavMenu> tenantNavMenus = tenantNavMenuService.list(new QueryWrapper<TenantNavMenu>().eq("tenant_id", tenantId));
        List<Long> ids = tenantNavMenus.stream().map(item -> item.getNavMenuId()).collect(Collectors.toList());
        List<NavMenuEntity> navMenuAll = this.listByIds(ids);
        List<TreeVO> treeVOS = navMenuAll.stream().map(navMenu -> {
            TreeVO treeVO = new TreeVO();
            treeVO.setLabel(navMenu.getLabel());
            treeVO.setId(navMenu.getId());
            treeVO.setParentId(navMenu.getParentId());
            return treeVO;
        }).collect(Collectors.toList());
        List<TreeVO> listLevelTop = treeVOS.stream().filter(navMenu ->
                navMenu.getParentId().equals(0L)
        ).map(item -> {
            Long a = treeVOS.stream().filter(item2 -> item2.getParentId().equals(item.getId())).count();
            if (a.compareTo(0L) == 1) {
                item.setChildren(getChildrenTree(item, treeVOS));
            } else {
                item.setChildren(null);
            }
            return item;
        }).collect(Collectors.toList());
        return listLevelTop;
    }

    @Override
    public List<DictBizVO> treeDict() {

        List<NavMenuEntity> allRoleNavMenu = this.list();
        List<DictBizVO> dictBizVOS = allRoleNavMenu.stream().map(navMenu -> {
            DictBizVO dictBizVO = new DictBizVO();
            Long a = allRoleNavMenu.stream().filter(item2 -> item2.getParentId().equals(navMenu.getId())).count();
            dictBizVO.setHasChildren(a.compareTo(0L)==1);
            dictBizVO.setLabel(navMenu.getLabel());
            dictBizVO.setValue(navMenu.getId().toString());
            dictBizVO.setParentId(navMenu.getParentId());
            return dictBizVO;
        }).collect(Collectors.toList());
        List<DictBizVO> listLevelTop = dictBizVOS.stream().filter(dictBizVO ->
                dictBizVO.getParentId().compareTo(0L)==0
        ).map(item -> {
            item.setChildren(CascaderUtil.getChildren(item, dictBizVOS));
            return item;
        }).collect(Collectors.toList());
        DictBizVO parent = new DictBizVO();
        parent.setId(0L);
        parent.setParentId(0L);
        parent.setParentName("顶级菜单");
        parent.setLabel("顶级菜单");
        parent.setChildren(listLevelTop);
        parent.setValue("0");
        parent.setHasChildren(false);
        List<DictBizVO> dictBizVOList = new ArrayList<>();
        dictBizVOList.add(parent);
        return dictBizVOList;
    }


    @Override
    public boolean deleteAll(List<Long> ids) {
        List<Long> longList = new ArrayList<>();
        ids.forEach(item -> {
            longList.add(item);
            List<NavMenuEntity> list = this.baseMapper.selectList(new QueryWrapper<NavMenuEntity>().eq("parent_id", item));
            if(list.size()>0){
                longList.addAll(this.getNavChildren(list));
            }
        });
        log.info("deleteAll:{}",longList);
        if(longList.size()>0){
            this.baseMapper.deleteBatchIds(longList);
            roleNavMenuMapper.delete(new QueryWrapper<RoleNavMenu>().in("nav_menu_id",longList));
//            tenantNavMenuService.remove(new QueryWrapper<TenantNavMenu>().in("nav_menu_id",longList));
        }
        return true;
    }

    private List<Long> getNavChildren(List<NavMenuEntity> list) {
        List<Long> all = new ArrayList<>();
        list.forEach(item -> {
            all.add(item.getId());
            List<NavMenuEntity> list2 = this.baseMapper.selectList(new QueryWrapper<NavMenuEntity>().eq("parent_id", item.getId()));
            if(list2.size()>0){
                all.addAll(this.getNavChildren(list2));
            }
        });

        return all;
    }

    @Override
    @Async
    public void initTenant(TenantDTO tenantDTO) {
        List<NavMenuEntity> list = this.baseMapper.selectList(new QueryWrapper<NavMenuEntity>().in("label", Func.toStrList(NovaDefaultConstant.DEFAULT_NAV_MENU)));
        List<TenantNavMenu> navMenus = list.stream().map(item->{
            TenantNavMenu tenantNavMenu = new TenantNavMenu();
            tenantNavMenu.setNavMenuId(item.getId());
            tenantNavMenu.setTenantId(tenantDTO.getTenant());
            return tenantNavMenu;
        }).collect(Collectors.toList());
        tenantNavMenuService.saveBatch(navMenus);
    }
}
